import mx.xpath.XPathAPI;

import org.molamil.acto.core.Logger;
import org.molamil.acto.core.ParserError;
import org.molamil.acto.pages.AbstractMovieContext;
import org.molamil.acto.pages.MovieContext;
import org.molamil.acto.pages.PageContext;
import org.molamil.acto.pages.PagesParseConfVO;
import org.molamil.acto.props.PropsParser;
import org.molamil.commons.StringUtil;

/**
 * Parses an XML with pages configuration.
 *
 * @author Jorge Hernandez
 */
class org.molamil.acto.pages.PagesParser {
	
	
	// Constants
	
	public static var ERROR_INVALID_ROOT:String = "ERROR: Invalid node: <pages> expected, <{node}> found.";
	
	
	// Properties
	
	private static var log:Logger = Logger.getLogger("PagesParser");
	
	
	// Functions
	
	/**
	 * Static parser that analyzes the given XML block and creates <code>PageContext</code> objects.
	 * 
	 * @param   xml Xml block containing pages configuration - &lt;pages&gt;
	 * @return  An array containing PageContext objects.
	 * @throws	org.molamil.acto.core.ParserError
	 */
	public static function parse(xml:XML):PagesParseConfVO {
		
		log.info("parse()");
		
		if (xml.firstChild.nodeName != "pages") {
			log.severe("ParserError");
			var msg:String = StringUtil.replace(ERROR_INVALID_ROOT, "{node}", xml.firstChild.nodeName);
			throw new ParserError(msg);
		}
		
		// Create the vo.
		var vo:PagesParseConfVO = new PagesParseConfVO();
		
		// Create the arrays.
		var pl:Array = new Array();
		var ml:Array = new Array();
		
		// Get pages.
		var pageNodes:Array = XPathAPI.selectNodeList(xml.firstChild, "/pages/page");
		log.debug(pageNodes.length + " pages found");
		
		// Iterate the pages.
		for (var i:Number = 0; i < pageNodes.length; i++) {
			
			log.debug("processing page node " + i);
			
			var pageNode:XMLNode = pageNodes[i];
			var context:PageContext = parsePageContext(pageNode);
				
			pl.push(context);
			
		}
		
		// Set the pages.
		vo.pageList = pl;
		
		// Get movies.
		var movieNodes:Array = XPathAPI.selectNodeList(xml.firstChild, "/pages/movie");
		log.debug(movieNodes.length + " movies found");
		
		// Iterate the movies.
		for (var i:Number = 0; i < movieNodes.length; i++) {
			
			log.debug("processing movie node " + i);
			
			var movieNode:XMLNode = movieNodes[i];
			var context:MovieContext = parseMovieContext(movieNode);
				
			ml.push(context);
			
		}
		
		// Set the movies.
		vo.movieList = ml;

		return vo;
		
	}
	
	private static function parseAbstractContext(node:XMLNode, context:AbstractMovieContext):AbstractMovieContext {
		
		context.name = node.attributes["name"];
		log.debug("name = " + context.name);
		
		context.title = node.attributes["title"];
		log.debug("title = " + context.title);
		
		context.type = node.attributes["type"];
		log.debug("type = " + context.type);
		
		context.target = node.attributes["target"];
		log.debug("target = " + context.target);
		
		context.base = node.attributes["base"];
		log.debug("base = " + context.base);
		
		context.container = node.attributes["container"];
		log.debug("container = " + context.container);
		
		context.className = node.attributes["class"];
		log.debug("className = " + context.className);
		
		context.isPreload = node.attributes["preload"].toLowerCase != "false";
		log.debug("isPreload = " + context.isPreload);
		
		var depends:String = StringUtil.replace(node.attributes["depends"], " ", "");
		context.depends = depends != "" ? depends.split(",") : null;
		log.debug("depends = " + context.depends);
		
		context.props = PropsParser.parse(new XML(node.toString()));
		
		return context;
			
	}
	
	private static function parseMovieContext(node:XMLNode):MovieContext {
		
		var context:MovieContext = MovieContext(parseAbstractContext(node, new MovieContext()));
	
		return context;
			
	}
	
	private static function parsePageContext(node:XMLNode):PageContext {
		
		var context:PageContext = PageContext(parseAbstractContext(node, new PageContext()));
		
		context.alias = node.attributes["alias"];
		log.debug("alias = " + context.alias);
		
		context.parentName = node.attributes["parent"];
		log.debug("parentName = " + context.parentName);
		
		context.role = node.attributes["role"];
		log.debug("role = " + context.role);
		
		return context;
			
	}
	
	
}